<?php

namespace Ysy\HyperfImport\Importer\Driver;

use Box\Spout\Common\Exception\{InvalidArgumentException, IOException, SpoutException};
use Box\Spout\Common\Type;
use Box\Spout\Reader\Common\Creator\ReaderFactory;
use Box\Spout\Reader\CSV\Reader as CsvReader;
use Generator;
use RuntimeException;

class StreamExcelDriver implements DriverInterface
{
    public function read(string $filePath, string $extension, bool $skipHeader = true, array $options = [], int &$totalCount = 0): Generator
    {
        try {
            $readAllSheets = $options['read_all_sheets'] ?? True;
            $totalCount = 0;

            # 映射文件类型
            $typeMap = [
                'xlsx' => Type::XLSX,
                'csv'  => Type::CSV,
                'ods'  => Type::ODS,
            ];

            $spoutType = $typeMap[$extension];

            $reader = ReaderFactory::createFromType($spoutType);

            # CSV 配置（3.3 兼容旧方法）
            if ($reader instanceof CsvReader) {
                // 确认是CSV阅读器后，才调用CSV专属方法（3.3文档明确支持）
                $reader->setEncoding($options['encoding'] ?? 'UTF-8');
                $reader->setFieldDelimiter($options['delimiter'] ?? ',');
                $reader->setFieldEnclosure($options['enclosure'] ?? '"');
            }

            $reader->open($filePath);

            foreach ($reader->getSheetIterator() as $sheet) {
                $sheetName = $sheet->getName();
                $rowIndex = 0;
                foreach ($sheet->getRowIterator() as $row) {
                    $rowIndex++;
                    if ($skipHeader && $rowIndex === 1) continue;
                    $totalCount ++;
                    yield [
                        'sheet_name' => $sheetName,
                        'row_index' => $rowIndex,
                        'data' => $row, // Spout的$row直接是数组，与ExcelDriver的数据结构对齐
                        'current_count' => $totalCount
                    ];
                }
                if (!$readAllSheets) break;
            }

            # 初始化Spout阅读器
        } catch (InvalidArgumentException $e) {
            throw new RuntimeException("参数错误：{$e->getMessage()}", 400, $e);
        } catch (IOException $e) {
            throw new RuntimeException("文件操作失败：{$e->getMessage()}", 500, $e);
        } catch (SpoutException $e) {
            throw new RuntimeException("解析失败：{$e->getMessage()}", 500, $e);
        } finally {
            if ($reader) $reader->close();
        }
    }
}